package com.itxixi.domain.strategy.service.raffle;

import com.itxixi.domain.strategy.model.entity.RaffleFactorEntity;
import com.itxixi.domain.strategy.model.entity.RuleActionEntity;
import com.itxixi.domain.strategy.model.entity.RuleMatterEntity;
import com.itxixi.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import com.itxixi.domain.strategy.repository.IStrategyRepository;
import com.itxixi.domain.strategy.service.armory.IStrategyDispatch;
import com.itxixi.domain.strategy.service.rule.ILogicFilter;
import com.itxixi.domain.strategy.service.rule.factory.DefaultLogicFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Fuzhengwei bugstack.cn @小傅哥
 * @description 默认的抽奖策略实现
 * @create 2024-01-06 11:46
 */
@Slf4j
@Service        //实现模板父类的抽象方法 以完善流程
public class DefaultRaffleStrategy extends AbstractRaffleStrategy {

    @Resource
    private DefaultLogicFactory logicFactory;

    public DefaultRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch) {
        super(repository, strategyDispatch);
    }
                                                                                           //父类传入所有的ruleModel 然后一个一个去调用对应的过滤器去过滤规则
    @Override                                      //RaffleFactorEntity.builder().userId(userId).strategyId(strategyId).build()  //rule_blacklist,rule_weight
    protected RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> doCheckRaffleBeforeLogic(RaffleFactorEntity raffleFactorEntity, String... logics) {

        //获取规则引擎工厂提供的部分 工厂生产的过滤器     //return (Map<String, ILogicFilter<T>>) (Map<?, ?>) logicFilterMap; 已自动配置
        Map<String, ILogicFilter<RuleActionEntity.RaffleBeforeEntity>> logicFilterGroup = logicFactory.openLogicFilter();
                                                                                //("rule_weight", RuleWeightLogicFilter )
                                                                                //("rule_blacklist",RuleBackListLogicFilter)
        // 黑名单规则优先过滤 根据父类传进来的ruleModel == logics一个一个去过滤
        String ruleBackList = Arrays.stream(logics)//rule_blacklist,rule_weight -> rule_blacklist
                .filter(str -> str.contains(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode()))//rule_blacklist
                .findFirst()
                .orElse(null);

        //如果有黑名单 调用RuleBackListLogicFilter过滤器进行过滤
        if (StringUtils.isNotBlank(ruleBackList)) {       //RuleBackListLogicFilter           //rule_blacklist
            ILogicFilter<RuleActionEntity.RaffleBeforeEntity> logicFilter = logicFilterGroup.get(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode());
            //RuleActionEntity ：code info ruleModel data(strategyId awardId ruleWeightValueKey）
            //RuleMatterEntity : userId strategyId awardId ruleModel
            //装配物料
            RuleMatterEntity ruleMatterEntity = new RuleMatterEntity();
            ruleMatterEntity.setUserId(raffleFactorEntity.getUserId());//父类传过来(Factor)
            ruleMatterEntity.setAwardId(ruleMatterEntity.getAwardId());//NULL
            ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId());//父类传过来(Factor)
            ruleMatterEntity.setRuleModel(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode());//rule_blacklist
                        // 也可以直接用父类传过来的字段setRuleModel（ruleBackList）(Factor)

            //装配完物料  RuleBackListLogicFilter.filter(ruleMatterEntity) 开始调用过滤操作
            RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> ruleActionEntity = logicFilter.filter(ruleMatterEntity);
            //开始过滤 ：1.根据ruleMatterEntity（UserId不用于查询）                              //（11用StrategyId AwardId RuleModel）ruleMatterEntity
            //              查询IStrategyRuleDao 根据strategyRuleEntity实体 得到rule_value 1.查到100：user001，user002，user003

            //           2. UserID用于判断是否存在于黑名单 如果在 返回动作实体 代表进行接管         //22 ruleMatterEntity
            //             RuleActionEntity ：code info ruleModel data(strategyId awardId ruleWeightValueKey）
            //              .ruleModel(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode())//33可以是ruleMatterEntity传入的ruleModel
            //              .data(RuleActionEntity.RaffleBeforeEntity.builder()
            //                      .strategyId(ruleMatterEntity.getStrategyId())             //44是ruleMatterEntity传入的
            //                      .awardId(awardId)                                         //000 不是ruleMatterEntity传入的传入的
            //                                                                        而是根据查到的rule_value 得到 Integer awardId
            //                      .build())

            //              .code(RuleLogicCheckTypeVO.TAKE_OVER.getCode())//修改状态 接管后续的流程
            //              .info(RuleLogicCheckTypeVO.TAKE_OVER.getInfo())//修改状态 接管后续的流程

            if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) {
                return ruleActionEntity;//用户只有一个人 你是黑名单就可以直接滚了
            }
        }

        // 顺序过滤剩余规则
        List<String> ruleList = Arrays.stream(logics)//rule_blacklist,rule_weight -> rule_weight
                .filter(s -> !s.equals(DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode()))
                .collect(Collectors.toList());//rule_weight

        RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> ruleActionEntity = null;//动作实体 设为null即保证没有规则也能返回
        for (String ruleModel : ruleList) {                             //获取logicFilter对象 用logicFilter去过滤处理
            //列表循环  调赌对应的用RulexxxLogicFilter过滤器进行过滤 RuleWeightLogicFilter...
            ILogicFilter<RuleActionEntity.RaffleBeforeEntity> logicFilter = logicFilterGroup.get(ruleModel);

            //RuleMatterEntity : userId strategyId awardId ruleModel
            //装配物料
            RuleMatterEntity ruleMatterEntity = new RuleMatterEntity();

            ruleMatterEntity.setUserId(raffleFactorEntity.getUserId());//父类传过来(Factor)
            ruleMatterEntity.setAwardId(ruleMatterEntity.getAwardId());//父类传过来(Factor)
            ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId());//null
            ruleMatterEntity.setRuleModel(ruleModel);//父类传过来(Factor)

            //装配完物料   开始调用过滤操作
            ruleActionEntity = logicFilter.filter(ruleMatterEntity);
             //1.查询IStrategyRuleDao 根据strategyRuleEntity实体 得到rule_value
            // //11如果Map为空 就放行
               //22不为空 判断是否满足条件 然后再接管
            // .data(RuleActionEntity.RaffleBeforeEntity.builder()
            //        .strategyId(strategyId)//100001                                                       11 ruleMatterEntity
            //        .ruleWeightValueKey(analyticalValueGroup.get(nextValue))//102,103,104,105（String）   000 是rulevalue拆出来的value
            //        .build())
            // .ruleModel(DefaultLogicFactory.LogicModel.RULE_WIGHT.getCode())                     22可以是ruleMatterEntity传入的ruleModel
            // .code(RuleLogicCheckTypeVO.TAKE_OVER.getCode())
            // .info(RuleLogicCheckTypeVO.TAKE_OVER.getInfo())

            //非放行结果则顺序过滤
            log.info("抽奖前规则过滤 userId: {} ruleModel: {} code: {} info: {}", raffleFactorEntity.getUserId(), ruleModel, ruleActionEntity.getCode(), ruleActionEntity.getInfo());
            if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) return ruleActionEntity;
        }   //这个循环的设计主要是为了实现按顺序逐个检查规则，并在找到第一个不符合“允许”条件的规则 的动作实体

        return ruleActionEntity;
    }

}
